﻿/**
* @file uart_handle.c in FusionUnitXIH6
* @author rebeater
* @comment
* Create on 12/3/21 5:22 PM
* @version 1.0
**/
#include "global_defines.h"
#include <main.h>
#include <rtcommon.h>
#include <memory.h>
#include <usart.h>
#include "uart_handle.h"
#include "rtcommon.h"
#include "stm32h7xx_hal_uart.h"
#include "nav_struct.h"
#include "stm32h7xx_it.h"
#include "navmsg.h"
#include "GnssParseRaw.h"
#include "nmea.h"
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_usart3_tx;
extern DMA_HandleTypeDef hdma_usart6_tx;
extern DMA_HandleTypeDef hdma_usart6_rx;
extern uint8_t gnss_buff[UART_RX_BUFFER_LENGTH];
extern uint8_t rx_buff[UART_RX_BUFFER_LENGTH];
extern uint8_t uart1_rx_buff[UART_RX_BUFFER_LENGTH];
extern uint8_t uart6_rx_buffer[UART_RX_BUFFER_LENGTH];
extern uint8_t rtcm3_buff[UART_RX_BUFFER_LENGTH];
extern osMessageQId gnssDataQueueHandle;
extern __IO uint32_t valid_length;
extern SemaphoreHandle_t uartGnssReadySemaphoreHandle;

uint32_t rtcm3_length = 0;

char *FindNmea(const uint8_t *start, const uint8_t *end) {
  uint8_t *p = (uint8_t *)start;
  while (p != end) {
	if ((*p == '$') && (*(p + 1) == 'G')) {
	  return (char *)p;
	}
	p++;
  }
  return NULL;
}
void UART_DMA_RX_STOP(UART_HandleTypeDef *huart) {
  __HAL_UART_CLEAR_IDLEFLAG(huart);
  HAL_DMA_Abort(huart->hdmarx);
  CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
  CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE));
  huart->RxState = HAL_UART_STATE_READY;
  huart->RxISR = NULL;
}/* At end of Tx process, restore huart->gState to Ready */


void USER_UART_IRQHandler(UART_HandleTypeDef *huart) {
  GnssMsg gnss = {0, 0, 0, 0};
  BaseType_t woke;
  char *p;
  if (huart->Instance == USART6) {
	/*转发差分改正数，发送到UART2,给GNSS接收机 */
	if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET) {
	  UART_DMA_RX_STOP(huart);
#if 0 /*目前采用电台直连，不需要此端口，故 取消转发 */
	  int cnt = UART_RX_BUFFER_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart6_rx);
	  if (cnt > 1 && cnt < UART_RX_BUFFER_LENGTH) {
		memcpy(rtcm3_buff,uart6_rx_buffer,cnt);
#if  GNSS_RCV == GNSS_RCV_MXT906B
		HAL_UART_Transmit_DMA(&huart2, (uint8_t *)rtcm3_buff, cnt);
#elif GNSS_RCV == GNSS_RCV_UB482
		HAL_UART_Transmit_DMA(&huart5, (uint8_t *)rtcm3_buff, cnt);
#endif
	}
#endif
	  SCB_CleanInvalidateDCache_by_Addr((uint32_t *)uart6_rx_buffer, UART_RX_BUFFER_LENGTH);
	  HAL_UART_Receive_DMA(huart, uart6_rx_buffer, UART_RX_BUFFER_LENGTH);
	}
  } else if (huart->Instance == GNSS_UART_INSTANCE) {
	if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET) {
	  __HAL_UART_CLEAR_IDLEFLAG(huart);
	  HAL_UART_DMAStop(huart);
	  int cnt = UART_RX_BUFFER_LENGTH - __HAL_DMA_GET_COUNTER(huart->hdmarx);
	  if (cnt > 1 && cnt < UART_RX_BUFFER_LENGTH) {
		memcpy(gnss_buff, rx_buff, cnt);
		*(gnss_buff + cnt) = 0;
		p = FindNmea(gnss_buff, gnss_buff + cnt);
		if (p != NULL) {
		  /*for debug*/
		  PARSE_GNSS(p, &gnss);
		  xQueueSendFromISR(gnssDataQueueHandle, &gnss, &woke);
		};
		valid_length = cnt;
		xSemaphoreGiveFromISR(uartGnssReadySemaphoreHandle, &woke);
		HAL_UART_Transmit_DMA(&huart1, (uint8_t *)gnss_buff, cnt);
	  }
	  SCB_CleanInvalidateDCache_by_Addr((uint32_t *)rx_buff, UART_RX_BUFFER_LENGTH);
	  HAL_UART_Receive_DMA(&huart2, rx_buff, UART_RX_BUFFER_LENGTH);
	}
  }
}
